package com.missilike.biz.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.missilike.biz.*;
import com.missilike.core.domain.ContentRequest;
import com.missilike.core.domain.DeleteContentReuquest;
import com.missilike.core.enums.ContentType;
import com.missilike.core.exception.BizException;
import com.missilike.core.exception.SystemException;
import com.missilike.core.result.BizResultCode;
import com.missilike.core.result.CommonResult;
import com.missilike.core.utils.ResultUtils;
import com.missilike.domain.request.MilAccountContentStatusForm;
import com.missilike.domain.response.MilAccountInfo;
import com.missilike.domain.response.MilUserFeeds;
import com.missilike.domain.response.RewardRecordInfo;
import com.missilike.repository.entity.*;
import com.missilike.repository.entity.extend.MilContentAppreciateExtend;
import com.missilike.repository.entity.extend.MilContentCommentExtend;
import com.missilike.repository.entity.extend.MilContentExtend;
import com.missilike.repository.mapper.MilAccountContentMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author pengpengli
 * @since 2018-12-19
 */
@Service
public class MilAccountContentServiceImpl extends ServiceImpl<MilAccountContentMapper, MilAccountContent> implements IMilAccountContentService {

    private IMilContentAppreciateService appreciateService;
    private IMilContentCommentService commentService;
    private final IMilFollowRelationshipService followRelationshipService;
    private final IMilFriendRelationshipService friendRelationshipService;
    private  IMilAccountService accountService;
    private final IMilPhotoService photoService;
    private IMilContentTransmitService transmitService;
    private IMilContentCollectionService contentCollectionService;
    private IMilRewardRecordService rewardRecordService;
    private IMilAccountAccessContentService milAccountAccessContentService;
    @Autowired
    public MilAccountContentServiceImpl(IMilFollowRelationshipService followRelationshipService,
                                        IMilFriendRelationshipService friendRelationshipService,
                                        IMilContentCommentService contentCommentService,
                                        IMilPhotoService photoService,
                                        IMilRewardRecordService rewardRecordService,
                                        IMilAccountAccessContentService milAccountAccessContentService
    ) {
        this.followRelationshipService = followRelationshipService;
        this.friendRelationshipService = friendRelationshipService;
        this.commentService = contentCommentService;
        this.photoService = photoService;
        this.rewardRecordService = rewardRecordService;
        this.milAccountAccessContentService=milAccountAccessContentService;
    }

    public static final int FORWART_TYPE = 3;

    @Override
    public void setAppreciateService(MilContentAppreciateServiceImpl milContentAppreciateService) {
        appreciateService = milContentAppreciateService;
    }

    @Override
    public void setContentTransmitService(IMilContentTransmitService milContentTransmitService) {
        this.transmitService = milContentTransmitService;
    }

    @Override
    public void setCollectionService(IMilContentCollectionService collectionService) {
        this.contentCollectionService = collectionService;
        this.contentCollectionService.setAccountContentService(this);
    }

    @Override
    public void setAccountService(IMilAccountService accountService) {
        this.accountService = accountService;
    }

    @Override
    public IPage<MilAccountContent> getList(Page<MilAccountContent> page) {
        return this.page(page, null);
    }

    @Override
    public void status(MilAccountContentStatusForm milAccountContentStatusForm) {
        MilAccountContent content = new MilAccountContent();
        content.setContentStatus(milAccountContentStatusForm.getStatus());
        baseMapper.update(content, new UpdateWrapper<MilAccountContent>()
                .lambda()
                .in(MilAccountContent::getId, Arrays.asList(milAccountContentStatusForm.getContentIds()))
        );
    }


    @Override
    public boolean deleteContent(DeleteContentReuquest reuquest) {
        MilAccountContent milAccountContent = baseMapper.selectOne(new QueryWrapper<MilAccountContent>().lambda()
                .eq(MilAccountContent::getAccountId, reuquest.getAuthorAccountId())
                .eq(MilAccountContent::getId, reuquest.getContentId())
        );
        if (milAccountContent == null) {
            throw new SystemException(BizResultCode.ARTICLE_CONTENT_EXISTENT.getCode(), BizResultCode.ARTICLE_CONTENT_EXISTENT.getMsg());
        }
        baseMapper.deleteById(milAccountContent.getId());
        return true;
    }


    public CommonResult sendContent(ContentRequest request) {
        if (request.getContentType() == null) {
            return ResultUtils.error(90001, "contentType参数不能为空");
        }
        if (!request.getContentType().equals(1) && !request.getContentType().equals(2) && !request.getContentType().equals(3)) {
            return ResultUtils.error(90001, "contentType参数不正确");
        }

        if (request.getContentType().equals(1)) {
            if (StringUtils.isBlank(request.getContentMessage()) && (request.getContentOssList() == null || request.getContentOssList().size() <= 0)
                    && (request.getContentVoiceOssId() == null || request.getContentVoiceOssId() <= 0)) {
                return ResultUtils.error(90001, "参数不能为空");
            }
            if (request.getContentOssList() != null && request.getContentOssList().size() > 0) {
                for (Long id : request.getContentOssList()) {
                    MilPhoto photo = photoService.getById(id);
                    if (photo == null || photo.getId() <= 0) {
                        return ResultUtils.error(99901, "图片Id不存在");
                    }
                }
            }
            if (request.getContentVoiceOssId() != null && request.getContentVoiceOssId() > 0) {
                MilPhoto photo = photoService.getById(request.getContentVoiceOssId());
                if (photo == null || photo.getId() <= 0) {
                    return ResultUtils.error(99901, "图片Id不存在");
                }
            }
        }
        if (request.getContentType().equals(2)) {
            if (StringUtils.isBlank(request.getContentMessage())) {
                return ResultUtils.error(90001, "contentMessage参数不能为空");
            }
        }
        if (request.getContentType().equals(3)) {
            if (request.getContentTransmitId() == null || request.getContentTransmitId() <= 0) {
                return ResultUtils.error(90001, "ContentTransmitId参数不能为空");
            }
            MilAccountContent transmContent = baseMapper.selectById(request.getContentTransmitId());
            if (transmContent == null) {
                return ResultUtils.error(90001, "转发内容为空");
            }
        }
        accountService.getAccount(request.getAccountId());
        MilAccountContent content = new MilAccountContent(
                request.getContentType(), request.getContentTitle(), request.getContentMessage(),
                1, request.getAccountId(), LocalDateTime.now(),
                request.getLocation(), StringUtils.join(request.getContentOssList(), "|"), request.getContentVoiceOssId(),
                request.getContentTransmitId(), request.getLocationCity());

        baseMapper.insert(content);
        return ResultUtils.ok(content);
    }


    @Override
    public List<MilUserFeeds> getUserFeeds(String id, Long lastId, Integer pageSize, Integer type) {
        List<MilUserFeeds> userFeeds = new ArrayList<>();
        if (StringUtils.isBlank(id)) {
            return userFeeds;
        }
        Set<String> userIds = new HashSet<>();
        userIds.add(id);
        return getFeeds(userIds, lastId, pageSize, type);
    }


    @Override
    public List<MilUserFeeds> getFeeds(String id, Long lastId, Integer pageSize, Integer type) {
        List<MilUserFeeds> userFeeds = new ArrayList<>();
        if (StringUtils.isBlank(id)) {
            return userFeeds;
        }
        List<MilAccountInfo> friends = friendRelationshipService.getAllFriends(id);
        List<MilAccountInfo> watchingUsers = followRelationshipService.watchingUsers(id);

        Set<String> userIds = Stream.concat(friends.stream().map(MilAccountInfo::getId).collect(Collectors.toList()).stream(),
                watchingUsers.stream().map(MilAccountInfo::getId).collect(Collectors.toList()).stream()).collect(Collectors.toSet());
        userIds.add(id);

        return getFeeds(userIds, lastId, pageSize, type);
    }



    @Override
    public List<MilUserFeeds> getFollowUsersFeeds(String id, Long lastId, Integer pageSize, Integer type) {
        List<MilUserFeeds> userFeeds = new ArrayList<>();
        if (StringUtils.isBlank(id)) {
            return userFeeds;
        }
        List<MilAccountInfo> watchingUsers = followRelationshipService.watchingUsers(id);
        Set<String> userIds = watchingUsers.stream().map(MilAccountInfo::getId).collect(Collectors.toList()).stream().collect(Collectors.toSet());
        return getFeeds(userIds, lastId, pageSize, type);
    }


    @Override
    public void setEquipmentService(IMilEquipmentService iMilEquipmentService) {
        accountService.setEquipmentService(iMilEquipmentService);
    }


    private List<MilUserFeeds> getFeeds(Set<String> userIds, Long lastId, Integer pageSize, Integer type) {
        List<MilUserFeeds> userFeeds = new ArrayList<>();
        QueryWrapper<MilAccountContent> contentQusery = new QueryWrapper();
        contentQusery.lambda().in(MilAccountContent::getAccountId, userIds);
        if (lastId != null && lastId > 0) {
            contentQusery.lambda().lt(MilAccountContent::getId, lastId);
        }
        if (type.equals(1)) {
            contentQusery.lambda().ne(MilAccountContent::getContentType, ContentType.LONGTEXT.getValue());//非长文
        } else if (type.equals(2)) {
            contentQusery.lambda().eq(MilAccountContent::getContentType, ContentType.LONGTEXT.getValue());//长文
        }
        contentQusery.lambda().orderByDesc(MilAccountContent::getCreateTime);
        contentQusery.last(" limit " + pageSize);
        List<MilAccountContent> contents = baseMapper.selectList(contentQusery);
        for (MilAccountContent c : contents) {
            MilUserFeeds milUserFeed = getFeed(c);
            userFeeds.add(milUserFeed);
        }
        return userFeeds;
    }




    public List<MilAccountContent> getForwardList(Long id) {
        QueryWrapper<MilAccountContent> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(MilAccountContent::getId, id).eq(MilAccountContent::getContentType, FORWART_TYPE);
        return baseMapper.selectList(queryWrapper);
    }

    @Override
    public MilContentExtend getContent(MilAccountContent content) {
        MilContentExtend contentExtend = new MilContentExtend();
        BeanUtils.copyProperties(content, contentExtend);
        if (StringUtils.isNotBlank(content.getContentPhotoOssList())) {
            long[] ids = Arrays.stream(content.getContentPhotoOssList().split("\\|")).mapToLong(Long::parseLong).toArray();
            contentExtend.setPhotos(photoService.getPhotoUrls(ArrayUtils.toObject(ids)));
        }

        if (null != content.getContentVoiceOssId()) {
            contentExtend.setVoice(photoService.getById(content.getContentVoiceOssId()));
        }
        return contentExtend;
    }

    @Override
    public MilUserFeeds getUserFeedsById(Long id,String currentAccountId) {
        MilAccountContent content = this.getById(id);
        if (content==null){
            throw new BizException(BizResultCode.ACCOUNT_ARTICLE_NO_EXIST);
        }
        MilUserFeeds milUserFeeds=getFeed(content);
        if (StringUtils.isNotEmpty(currentAccountId)){
            MilAccountAccessContent queryContent=milAccountAccessContentService.getOne(new QueryWrapper<MilAccountAccessContent>().lambda()
                    .eq(MilAccountAccessContent::getAccountId,currentAccountId)
                    .eq(MilAccountAccessContent::getMilAccountContentId,id)
                    .eq(MilAccountAccessContent::getMilAccountContentAccountId,content.getAccountId())
                    .eq(MilAccountAccessContent::getMilAccountContentType,content.getContentType()));
            if (queryContent==null){
                queryContent=new MilAccountAccessContent(currentAccountId,id,content.getAccountId(),content.getContentType(),LocalDateTime.now());
            }else{
                queryContent.setQueryTime(LocalDateTime.now());
            }
            milAccountAccessContentService.saveOrUpdate(queryContent);
        }
        return milUserFeeds;
    }

    private MilUserFeeds getFeed(MilAccountContent c) {
        MilUserFeeds milUserFeed = new MilUserFeeds();
       List<RewardRecordInfo> recordInfos =  rewardRecordService.getRewardsForContent(c.getId());
        List<MilContentAppreciateExtend> appreciateUsers = new ArrayList<>();
        List<MilContentCommentExtend> contentComments = new ArrayList<>();

        appreciateUsers = appreciateService.getAppreciates(c.getId());
        contentComments = commentService.getComments(c.getId());
        milUserFeed.setComments(contentComments);
        milUserFeed.setAppreciates(appreciateUsers);
        milUserFeed.setContent(getContent(c));
        MilAccount user = accountService.getById(c.getAccountId());
        milUserFeed.setNickName(user.getNickName());
        milUserFeed.setAccount(user.getAccount());
        milUserFeed.setForwardTimes(getForwardList(c.getId()).size());
        milUserFeed.setCollectTimes(contentCollectionService.getCollectionList(c.getId()).size());
        milUserFeed.setRewards(recordInfos);
        milUserFeed.setRewardTotal(recordInfos.stream().mapToLong(m -> m.getRewardBalance().longValue()).sum());
        if (user.getFaceUrlId() != null && user.getFaceUrlId() > 0) {
            milUserFeed.setFaceUrl(photoService.getPhotoUrl(user.getFaceUrlId()));
        }
        if (c.getContentType().equals(ContentType.FORWARD.getValue())) {
            milUserFeed.setForward(this.getById(c.getContentTransmitId()));
        }
        return milUserFeed;
    }

    @Override
    public Integer getAccountContentCount(String accountId) {
        QueryWrapper<MilAccountContent> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(MilAccountContent::getAccountId, accountId);
        return baseMapper.selectCount(queryWrapper);
    }



}
